package main.database;

import com.mongodb.BasicDBObject;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import main.GlobalConfig;
import main.HanYu;
import main.TimeHelper;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class AuthorHelper {
    /**
     * 得到作者的id
     * @param author，作者的名字
     * @return
     */
    public static String getId(String author) {
        MongoCollection<Document> collection = DatabaseMan.Instance().GetCollection(GlobalConfig.collectionNameOfAuthor);
        FindIterable<Document> findIterable = collection.find(new BasicDBObject("name", author));
        MongoCursor<Document> cursor = findIterable.iterator();

        String result = null;
        if (cursor.hasNext()) {
            Document doc = cursor.next();
            result = doc.get("_id").toString();
        }
        cursor.close();

        return result;
    }

    /**
     * 根据给定的名字，查找作者是否存在
     * @param author，作者的名字
     * @return
     */
    public static boolean isAuthorExist(String author) {
        return AuthorHelper.getId(author) != null;
    }

    /**
     * 根据指定的作者id，取它的描述
     * @param id，作者的id
     * @return
     */
    public static String getIntroductionFromId(String id) {
        MongoCursor<Document> cursor = AuthorHelper.getSearchCursorFromId(id);

        String result = null;
        if (cursor.hasNext()) {
            Document doc = cursor.next();
            result = (String) doc.get("introduction");
        }
        cursor.close();

        return result;
    }

    /**
     * 根据作者的id，取作者的相关信息
     * @param id，作者的id
     * @return
     */
    public static Map<String, String> getInfomationFromId(String id) {
        MongoCursor<Document> cursor = AuthorHelper.getSearchCursorFromId(id);

        HashMap<String, String> result = null;
        if (cursor.hasNext()) {
            Document doc = cursor.next();
            result = new HashMap<>();
            result.put("name", (String) doc.get("name"));
            result.put("introduction", (String) doc.get("introduction"));
        }
        cursor.close();

        return result;
    }

    /**
     * 在数据库中新增一个作者的记录
     * @param name
     * @param introduction
     * @return
     */
    public static String addAuthor(String name, String introduction) {
        MongoCollection<Document> collection = DatabaseMan.Instance().GetCollection(GlobalConfig.collectionNameOfAuthor);
        String pinyin = HanYu.Instance().getStringPinYin(name);
        Document document = new Document("name", name)
                .append("pinyin", pinyin)
                .append("introduction", introduction)
                .append("money", 0)
                .append("createtime", TimeHelper.getFormattedNowString());

        collection.insertOne(document);
        return document.get("_id").toString();
    }

    /**
     * 根据模糊搜索法，搜索数据库中的所有相关信息
     * @param query
     * @return
     */
    public static List<String> getAuthorNameList(String query) {
        MongoCollection<Document> collection = DatabaseMan.Instance().GetCollection(GlobalConfig.collectionNameOfAuthor);
        FindIterable<Document> documents;

        if (query != null && !query.isEmpty()) {
            String regex = "\\B" + query + "|" + query + "\\B";
            Pattern pattern = Pattern.compile(regex);
            documents = collection.find(Filters.regex("name", pattern)).projection(Projections.include("name"));
        }
        else {
            documents = collection.find().projection(Projections.include("name"));
        }

        MongoCursor<Document> cursor = documents.iterator();

        List<String> result = new ArrayList<>();
        while (cursor.hasNext()) {
            Document doc = cursor.next();
            result.add((String) doc.get("name"));
        }
        cursor.close();

        return result;
    }

    /**
     * 根据作者的id，得到该作者的名字
     * @param id
     * @return
     */
    public static String getAuthorNameFromId(String id) {
        MongoCursor<Document> cursor = AuthorHelper.getSearchCursorFromId(id);

        String result = null;
        if (cursor.hasNext()) {
            Document doc = cursor.next();
            result = (String) doc.get("name");
        }
        cursor.close();

        return result;
    }

    public static List<String[]> getAuthorArticleList(String id) {
        List<String[]> list = new ArrayList<>();

        MongoCollection<Document> collection = DatabaseMan.Instance().GetCollection(GlobalConfig.collectionNameOfArticle);
        FindIterable<Document> findIterable = collection.find(Filters.eq("author", id)).projection(Projections.include("_id", "title", "score"));
        MongoCursor<Document> cursor = findIterable.iterator();

        while(cursor.hasNext()) {
            Document doc = cursor.next();

            String[] strs = new String[3];
            strs[0] = doc.get("_id").toString();
            strs[1] = (String) doc.get("title");
            double dScore = (double) doc.get("score");
            strs[2] = ScoreHelper.getFormattedSecretScore(dScore);

            list.add(strs);
        }
        cursor.close();

        return list;
    }

    public static List<String[]> findAuthors(String key) {
        MongoCollection<Document> collection = DatabaseMan.Instance().GetCollection(GlobalConfig.collectionNameOfAuthor);
        //以 | 隔开正则表达式，最后一个是为了用户输入全名的英文（比如Priest）也能搜到
        String regex = "\\B" + key + "|" + key + "\\B" + "|" + key;
        Pattern pattern = Pattern.compile(regex);
        FindIterable<Document> findIterable = collection.find(Filters.regex("name", pattern)).projection(Projections.include("name", "introduction"));
        MongoCursor<Document> cursor = findIterable.iterator();

        List<String[]> authorList = new ArrayList<>();
        while(cursor.hasNext()) {
            Document doc = cursor.next();

            String name = doc.get("name").toString();
            String intro = doc.get("introduction").toString();
            String id = doc.get("_id").toString();

            String[] authors = new String[3];
            authors[0] = name;
            if (intro.length() <= 600) {
                authors[1] = intro;
            }
            else {
                authors[1] = intro.substring(0, 58);
            }
            authors[2] = id;

            authorList.add(authors);
        }

        return authorList;
    }

    public static List<String[]> findAuthorListFromTime(int limit) {
        List<String[]> result = new ArrayList<>();

        MongoCollection<Document> collection = DatabaseMan.Instance().GetCollection(GlobalConfig.collectionNameOfAuthor);
        Bson sortMethod = new Document("createtime", -1);
        FindIterable<Document> findIterable = collection.find().projection(Projections.include("name", "_id", "createtime")).sort(sortMethod);
        if (limit > 0) {
            findIterable = findIterable.limit(100);
        }
        MongoCursor<Document> cursor = findIterable.iterator();

        if (limit == 0) limit = Integer.MAX_VALUE;
        int count = 0;
        while (count < limit && cursor.hasNext()) {
            Document doc = cursor.next();
            String createTimeStr = doc.get("createtime").toString();
            Timestamp createTime = Timestamp.valueOf(createTimeStr);
            boolean within = TimeHelper.isTimeWithinWeeks(createTime, GlobalConfig.getInformationTimeRange());
            if (!within) break;

            String[] value = new String[2];
            value[0] = doc.get("_id").toString();
            value[1] = doc.get("name").toString();

            result.add(value);

            count++;
        }
        cursor.close();

        return result;
    }

    /**
     * 从数据库中搜索开头为指定字符（pinyin）的记录
     * @param startAlphabet
     * @return
     */
    public static List<String[]> findAuthorFromPinYin(String startAlphabet) {
        List<String[]> resultList = new ArrayList<>();
        MongoCollection<Document> collection = DatabaseMan.Instance().GetCollection(GlobalConfig.collectionNameOfAuthor);
        if (startAlphabet.length() != 0) {
            String regex = "^" + startAlphabet;
            Pattern pattern = Pattern.compile(regex);
            Bson sortMethod = new Document("pinyin", 1);
            FindIterable<Document> findIterable = collection.find(Filters.regex("pinyin", pattern))
                    .projection(Projections.include("name", "_id", "pinyin"))
                    .sort(sortMethod);
            MongoCursor<Document> cursor = findIterable.iterator();

            while(cursor.hasNext()) {
                Document doc = cursor.next();

                String[] result = new String[4];
                result[0] = doc.get("name").toString();
                result[1] = doc.get("_id").toString();
                result[2] = doc.get("pinyin").toString();

                resultList.add(result);
            }
        }
        return resultList;
    }

    private static MongoCursor<Document> getSearchCursorFromId(String id) {
        MongoCollection<Document> collection = DatabaseMan.Instance().GetCollection(GlobalConfig.collectionNameOfAuthor);
        FindIterable<Document> findIterable = collection.find(new BasicDBObject("_id", new ObjectId(id)));
        return findIterable.iterator();
    }
}
